﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Windows.Forms;

namespace Speedy
{
    public class Rapi
    {
        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeCloseHandle(int hobject);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeCreateFile(string lpfilename, int dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplatefile);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern long CeRapiInitEx(RAPIINIT prapiinit);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeRapiInit();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeRapiUninit();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeReadFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, int lpOverlapped);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeWriteFile(int hFile, byte[] lpBuffer, int nNumberofbytestoWrite, ref int lpNumberofBytesWritten, int lpOverlapped);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int GetLastError();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeSetEndOfFile(int hFile);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeGetFileSize(int hFile, int lpFileSizeHigh);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeGetLastError();

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeCreateProcess(string Filename, string param, int procAttr, int threadAttr, int boolh, int creFlags, int env, string curDir, int si, ref PROCESSINFO pi);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        private static extern int CeCreateDirectory(string lpPathName, int lpSecurityAttributes);

        private ProgressBar progBar;
        private Label m_infoLabel;
        public delegate void CopyFileCallBack(int bytesCopied, int totalBytes);

        private void CallBack(int bytesCopied, int totalBytes)
        {
            if ((progBar != null))
            {
                progressBar.Maximum = totalBytes;
            }
            //progressBar.Value = bytesCopied 
        }
        public ProgressBar progressBar
        {
            get { return progBar; }
            set { progBar = value; }
        }

        public Label InfoLabel
        {
            get { return m_infoLabel; }
            set { m_infoLabel = value; }
        }

        public bool PPCConnected()
        {
            int iConn = 0;
            iConn = CeRapiInit();
            return Convert.ToBoolean(iConn);
        }

        public bool copyFileToTerminal(string deskTopFileName, string TerminalFileName)
        {
            if ((progressBar != null))
            {
                progressBar.Visible = true;
            }
            if ((InfoLabel != null))
            {
                InfoLabel.Text = "Copy desktop file: " + deskTopFileName + " to Terminal as " + TerminalFileName;
                InfoLabel.Visible = true;
                InfoLabel.Update();
            }
            bool b = copyFileToTerminal(deskTopFileName, TerminalFileName, null);
            if ((progressBar != null))
            {
                progressBar.Visible = false;
            }
            if ((InfoLabel != null))
            {
                InfoLabel.Visible = false;
            }
            return b;
        }

        public int GetFileSize(string TerminalFileName)
        {
            int handle = 0;
            CeRapiInit();
            handle = CeCreateFile(TerminalFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
            int fileSize = CeGetFileSize(handle, 0);
            CeRapiUninit();
            return fileSize;
        }

        public bool copyFileToDesktop(string deskTopFileName, string TerminalFileName)
        {
            if ((progressBar != null))
            {
                progressBar.Visible = true;
            }
            if ((InfoLabel != null))
            {
                InfoLabel.Text = "Copy Terminalfile " + TerminalFileName + " to Desktop as " + deskTopFileName;
                InfoLabel.Visible = true;
                InfoLabel.Update();
            }
            bool b = copyFileToDesktop(deskTopFileName, TerminalFileName, null);
            if ((progressBar != null))
            {
                progressBar.Visible = false;
            }
            if ((InfoLabel != null))
            {
                InfoLabel.Visible = false;
            }
            return b;
        }

        public bool copyFileToTerminal(string deskTopFileName, string TerminalFileName, CopyFileCallBack cb)
        {
            int Handle = 0;
            int bufferSize = 0x8000;
            byte[] lpBuffer = new byte[bufferSize + 1];
            int lpNumberofBytesWritten = 0;

            CeRapiInit();
            Handle = CeCreateFile(TerminalFileName, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

            FileStream fs = new FileStream(deskTopFileName, FileMode.Open, FileAccess.Read);

            int fSize = (int)fs.Length;
            int bytesRead = 0;
            int bytesToRead = bufferSize;

            if (fSize < bufferSize) bytesToRead = fSize;
            BinaryReader r = new BinaryReader(fs);

            while ((bytesRead < fSize))
            {
                lpBuffer = r.ReadBytes(bytesToRead);
                CeWriteFile(Handle, lpBuffer, bytesToRead, ref lpNumberofBytesWritten, 0);
                bytesRead += bytesToRead;
                if (fSize - bytesRead < bufferSize) bytesToRead = fSize - bytesRead;
                if ((cb != null))
                {
                    cb(bytesRead, fSize);
                }
                else
                {
                    CallBack(bytesRead, fSize);
                }
            }
            CeCloseHandle(Handle);
            CeRapiUninit();
            r.Close();
            return true;
        }

        public bool copyFileToDesktop(string deskTopFileName, string TerminalFileName, CopyFileCallBack cb)
        {
            int Handle = 0;
            int bufferSize = 0x8000;
            byte[] lpBuffer = new byte[bufferSize + 1];
            System.IO.FileStream outFile = default(System.IO.FileStream);
            CeRapiInit();
            try
            {
                outFile = new System.IO.FileStream(deskTopFileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                int lpNumberofBytesRead = bufferSize;
                Handle = CeCreateFile(TerminalFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
                int fileSize = CeGetFileSize(Handle, 0);
                int bytesToRead = bufferSize;
                int bytesRead = 0;
                while (lpNumberofBytesRead > 0)
                {
                    CeReadFile(Handle, lpBuffer, bytesToRead, ref lpNumberofBytesRead, 0);
                    outFile.Write(lpBuffer, 0, lpNumberofBytesRead);
                    bytesRead += lpNumberofBytesRead;
                    if ((cb != null))
                    {
                        cb(bytesRead, fileSize);
                    }
                    else
                    {
                        CallBack(bytesRead, fileSize);
                    }
                }
                outFile.Close();
                CeCloseHandle(Handle);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            CeRapiUninit();
            return true;
        }

        public bool CreateDirectory(string Path)
        {
            CeRapiInit();
            Path = Strings.Left(Path, Strings.Len(Path) - 1);
            int i = CeCreateDirectory(Path, 0);
            CeRapiUninit();
            if (i == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public bool RunTerminalProgram(string fileName, string CmdLine)
        {
            PROCESSINFO pi = default(PROCESSINFO);
            int i = 0;
            CeRapiInit();
            if (CmdLine == string.Empty)
            {
                i = CeCreateProcess(fileName, null, 0, 0, 0, 0, 0, null, 0, ref pi);
            }
            else
            {
                //use a command line 
                i = CeCreateProcess(fileName, CmdLine, 0, 0, 0, 0, 0, null, 0, ref pi);
            }
            CeRapiUninit();
            if ((i == 0))
            {
                return true;
            }
            else
            {
                return false;
            }
        }





        public short FILE_ATTRIBUTE_NORMAL = 0x80;
        public const short INVALID_HANDLE_VALUE = -1;
        public int GENERIC_READ;
        public const int GENERIC_WRITE = 0x40000000;
        public const short CREATE_NEW = 1;
        public const short CREATE_ALWAYS = 2;
        public const short OPEN_EXISTING = 3;
        public const short ERROR_FILE_EXISTS = 80;
        public const short ERROR_INVALID_PARAMETER = 87;
        public const short ERROR_DISK_FULL = 112;

        [StructLayout(LayoutKind.Sequential)]
        public struct OSVERSIONINFO
        {
            public int dwOSVersionInfoSize;
            public int dwMajorVersion;
            public int dwMinorVersion;
            public int dwBuildNumber;
            public int dwPlatformId;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string szCSDVersion;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct RAPIINIT
        {
            public int cbSize;
            public int heRapiInit;
            public int hrRapiInit;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SECURITY_ATTRIBUTES
        {
            public int nLength;
            public int lpSecurityDescriptor;
            public int bInheritHandle;
        }


        [StructLayout(LayoutKind.Sequential)]
        public struct PROCESSINFO
        {
            public IntPtr hProcess;
            public IntPtr hThread;
            public IntPtr dwProcessId;
            public IntPtr dwThreadId;
        }
    }
}
